﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
namespace BrainTechLLC.ThreadSafeObjects
{
    using System;
    using System.Collections.Generic;
    using System.Reflection;

    public static class CacheDirty
    {
        public static ThreadSafeLookup<Type, List<PropertyInfo>> _cachedPropertyCache = new ThreadSafeLookup<Type, List<PropertyInfo>>();

        /// <summary>
        /// Marks all cached properties on each enumerable item as dirty/invalid
        /// </summary>
        public static int DirtyCachedProperties<T>(this IEnumerable<T> items) where T : class
        {
            int count = 0;
            foreach (T item in items)
            {
                if (item != null)
                {
                    count += item.DirtyCachedProperties<T>();
                }
            }
            return count;
        }

        /// <summary>
        /// Marks all cached properties on list entry as dirty/invalid
        /// </summary>
        public static int DirtyCachedProperties<T>(this List<T> items) where T : class
        {
            return DirtyCachedProperties<T>((IEnumerable<T>)items);
        }

        /// <summary>
        /// Marks all properties marked with the IsCached attribute on item as dirty
        /// </summary>
        public static int DirtyCachedProperties<T>(this T item) where T : class
        {
            int count = 0;
            List<PropertyInfo> props = _cachedPropertyCache[typeof(T)];
            if (props == null)
            {
                props = new List<PropertyInfo>();
                PropertyInfo[] propinfos = typeof(T).GetProperties();
                foreach (PropertyInfo prop in propinfos)
                {
                    object[] os = prop.GetCustomAttributes(typeof(IsCached), true);
                    if (os != null && os.Length > 0)
                    {
                        if ((os[0] as IsCached).Cached)
                        {
                            props.Add(prop);
                        }
                    }
                }

                _cachedPropertyCache.AddOrSet(typeof(T), props);
            }

            for (int n = 0; n < props.Count; n++)
            {
                PropertyInfo prop = props[n];
                object o = prop.GetValue(item, null);
                if (o != null)
                {
                    CacheBase cache = o as CacheBase;
                    if (cache != null)
                    {
                        count++;
                        cache.MarkDirty();
                    }
                    else
                    {
                        throw new Exception("Object " + o.ToString() + ", value of property " + prop.Name + ", does not inherit from CacheBase");
                    }
                }
            }

            return count;
        }
    }
}